package lambda;

import org.junit.Test;

import java.util.*;

/**
 * @Author com.alibaba.lizhen
 * @Date 2021/3/23 5:39 下午
 * @Version 1.0
 * @Description
 *
 * Lmabda表达式的语法总结： () -> ();
 *
 * 前置	                                                语法
 * 无参数无返回值	                            () -> System.out.println(“Hello WOrld”)
 * 有一个参数无返回值	                        (x) -> System.out.println(x)
 * 有且只有一个参数无返回值	                     x -> System.out.println(x)
 * 有多个参数，有返回值，有多条lambda体语句	    (x，y) -> {System.out.println(“xxx”);return xxxx;}；
 * 有多个参数，有返回值，只有一条lambda体语句	    (x，y) -> xxxx
 * 口诀：左右遇一省括号，左侧推断类型省
 *
 * 注：当一个接口中存在多个抽象方法时，如果使用lambda表达式，并不能智能匹配对应的抽象方法，因此引入了函数式接口的概念
 */
public class LambdaTest {


    /**
     * 场景1：
     */
    @Test
    public void test1(){
        //匿名内部类
        Comparator<Integer> cpt = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Integer.compare(o1,o2);
            }
        };

        TreeSet<Integer> set = new TreeSet<>(cpt);

        System.out.println("=========================");

        //使用lambda表达式
        Comparator<Integer> cpt2 = (x,y) -> Integer.compare(x,y);
        TreeSet<Integer> set2 = new TreeSet<>(cpt2);
    }

    /**
     * 场景2：
     */
    @Test
    public void test2(){
        List<Product> products = Arrays.asList(
                new Product(1000,"白色"),
                new Product(2000,"红色"),
                new Product(8100,"红色"),
                new Product(9000,"白色")
        );
        //原始方法，一个要求就得写一个函数，函数中只有判断条件不一样
        filterProductByColor(products).forEach(System.out::println);
        filterProductByPrice(products).forEach(System.out::println);
        System.out.println("======================");

        //优化一：使用策略模式，一种要求就得一种实现
        filterProductByPredicate(products,new ColorPredicate()).forEach(System.out::println);
        filterProductByPredicate(products,new PricePredicate()).forEach(System.out::println);
        System.out.println("======================");

        //优化2：使用匿名内部类
        filterProductByPredicate(products, new MyPredicate<Product>() {
            @Override
            public boolean test(Product product) {
                return product.getColor().equals("红色");
            }
        }).forEach(System.out::println);
        System.out.println("=====================");
        //优化3：lambda
        filterProductByPredicate(products, product -> product.getColor().equals("红色"))
                .forEach(System.out::println);


        //优化4：使用stream


    }

    // 使用jdk1.8中的Stream API进行集合的操作
    @Test
    public void test4(){
        List<Product> proList = Arrays.asList(
                new Product(1000,"白色"),
                new Product(2000,"红色"),
                new Product(8100,"红色"),
                new Product(9000,"白色")
        );
        // 根据价格过滤
        proList.stream()
                .filter((product) -> product.getPrice() < 8000)
                .limit(1)
                .forEach(System.out::println);

        // 根据颜色过滤
        proList.stream()
                .filter((product) -> product.getColor().equals("红色"))
                .forEach(System.out::println);

        // 遍历输出商品价格
        proList.stream()
                .map(Product::getPrice)
                .forEach(System.out::println);
    }

    // 筛选颜色为红色
    public  List<Product> filterProductByColor(List<Product> list){
        List<Product> prods = new ArrayList<>();
        for (Product product : list){
            if ("红色".equals(product.getColor())){
                prods.add(product);
            }
        }
        return prods;
    }

    // 筛选价格小于8千的
    public  List<Product> filterProductByPrice(List<Product> list){
        List<Product> prods = new ArrayList<>();
        for (Product product : list){
            if (product.getPrice() < 8000){
                prods.add(product);
            }
        }
        return prods;
    }


    public List<Product> filterProductByPredicate(List<Product> list,MyPredicate<Product> mp){
        List<Product> prods = new ArrayList<>();
        for (Product prod : list){
            if (mp.test(prod)){
                prods.add(prod);
            }
        }
        return prods;
    }
}
